﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using log4net;
using log4net.Config;
using SKBKontur.Cassandra.Logging.Storage;
using SKBKontur.Cassandra.Proxy;

namespace CassandraStressTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var temp = new Start();
            temp.Go();
            temp.Stop();
        }
    }

    public class Start
    {
        private readonly ILog Log; 
        private const int NumberOfTreads = 20;
        private const int WriteLogCount = 100000;  // note 5GB
        private const string filename1 = "LOG.out";
        private const string filename2 = "LOGErr.out";
        private StreamWriter sw;
        private StreamWriter sw2;


        public Start()
        {
            FileStream fs; 
            fs = new FileStream(filename1, FileMode.Create);
            sw = new StreamWriter(fs);
            Console.SetOut(sw);
            FileStream fs2;
            fs2 = new FileStream(filename2, FileMode.Create);
            sw2 = new StreamWriter(fs2);
            Console.SetError(sw2);

            XmlConfigurator.Configure(new FileInfo("log4net.config"));
            Log = LogManager.GetLogger("TestLogger");

            Console.WriteLine("Keyspace prepared!");
            sw.Flush();
            Console.WriteLine("Setup complete...");
            sw.Flush();

        }



        private void TestManyThreadsStart(WaitHandle semaphore)
        {
            semaphore.WaitOne();
            for(int i = 0; i < WriteLogCount; i++)
            {
                try
                {
                    int a = 0;
                    int b = 1;
                    b = b/a;
                }
                catch(Exception e)
                {
                    // note Все эксепшены добавлены для проверки нагрузки на запись в одну колонку и для простоты подсчета занимаемого места
                    Log.Info("Events Info!", e);
                    Log.Warn("Events Warn!", e);
                    Log.Debug("Events Debug!", e);
                    Log.Error("Events Error!", e);
                    Log.Fatal("Events Fatal!", e);
                }

            }


        }

        public void Go()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();

            var threads = new Thread[NumberOfTreads];

            var semaphore = new Semaphore(0, threads.Length);

            for (int i = 0; i < threads.Length; i++)
            {
                var tmp = new Thread(() => TestManyThreadsStart(semaphore)) { Name = i.ToString() };
                threads[i] = tmp;
            }

            for (int i = 0; i < threads.Length; i++)
                threads[i].Start();

            var speakerThread = new Thread(AnalyzeMassage);
            speakerThread.Start();

            semaphore.Release(threads.Length);

            for (int i = 0; i < threads.Length; i++)
                threads[i].Join();
            stopwatch.Stop();

            Console.WriteLine("All elapsed time: {0} ms", stopwatch.ElapsedMilliseconds);
            speakerThread.Abort();
        }

        private void AnalyzeMassage()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            while (true)
            {
                Thread.Sleep(60000);
                stopwatch.Stop();
                Appender.Configurator.StorageClusterManager.ReportStatistics();
                Console.Out.WriteLine("Elapsed time: {0} ms", stopwatch.ElapsedMilliseconds);
                Console.Out.Flush();
                stopwatch.Start();
            }
        }

        public void Stop()
        {
            sw.Close();
            sw2.Close();
        }
    }
}
